package com.imashimaro.serializer;

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


public class MyBeanSerializerModifier extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        // 遍历bean的成员属性
        for (BeanPropertyWriter writer : beanProperties) {
            Class<?> rawClass = writer.getType().getRawClass();
            // 判断字段的类型, 并注册一个自己的nullSerializer
            if (rawClass.isArray() || isCollectionType(rawClass)) {
                writer.assignNullSerializer(new NullValueSerializer.CollectionNullValueSerializer());
            } else if (isNumberType(rawClass)) {
                writer.assignNullSerializer(new NullValueSerializer.NumberNullValueSerializer());
            } else if (isCharType(rawClass)) {
                writer.assignNullSerializer(new NullValueSerializer.CharSequenceNullValueSerializer());
            } else if (rawClass.equals(Boolean.class)) {
                writer.assignNullSerializer(new NullValueSerializer.BooleanNullValueSerializer());
            }
        }
        return beanProperties;
    }


    /**
     * 判断是否是集合类型
     *
     * @param clazz
     * @return
     */
    protected boolean isCollectionType(Class clazz) {
        List<Class> list = Arrays.stream(clazz.getInterfaces()).collect(Collectors.toList());
        return list.contains(List.class) || list.contains(Set.class);
    }

    /**
     * 是否是字符类型
     *
     * @param clazz
     * @return
     */
    protected boolean isCharType(Class clazz) {
        List<Class> list = Arrays.stream(clazz.getInterfaces()).collect(Collectors.toList());
        return list.contains(CharSequence.class) || clazz.equals(Character.class);
    }

    /**
     * 是否是数值类型
     *
     * @param clazz
     * @return
     */
    protected boolean isNumberType(Class clazz) {
        return clazz.getSuperclass().equals(Number.class);
    }
}